# -*- coding: utf8 -*-
########################################################################
# Copyright (c) 2008 Burdakov Daniel <kreved@kreved.org>               #
#                                                                      #
# This file is part of PyWoW.                                          #
#                                                                      #
# PyWoW is free software: you can redistribute it and/or modify        #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or    #
# (at your option) any later version.                                  #
#                                                                      #
# PyWoW is distributed in the hope that it will be useful,             #
# but WITHOUT ANY WARRANTY; without even the implied warranty of       #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        #
# GNU General Public License for more details.                         #
#                                                                      #
# You should have received a copy of the GNU General Public License    #
# along with PyWoW.     If not, see <http://www.gnu.org/licenses/>.    #
########################################################################

from twisted.internet.protocol import ClientFactory
from realmpacketprotocol import RealmPacketProtocol
import packets
from constants import *
import SRP

class RealmClientProtocol(RealmPacketProtocol):
 def connectionMade(self):
  RealmPacketProtocol.connectionMade(self)
  self.packet_handlers = [
  (AUTH_CHALLENGE, packets.SAuthChallenge, self.onAuthChallenge, [SENT_CHALLENGE]),
  (AUTH_PROOF, packets.SAuthProof, self.onAuthProof, [SENT_PROOF]),
  (REALM_LIST, packets.SRealmList, self.onRealmList, [AUTHENTICATED]) ]
  self.username, self.password = self.factory.username, self.factory.password
  p = packets.CAuthChallenge()
  p.version1, p.version2, p.version3 = self.factory.version
  p.build, p.platform, p.os, p.country = self.factory.build, \
  self.factory.platform, self.factory.os, self.factory.country
  p.ip, p.I = 16777343, self.username # should be something else instead 16777343
  self.send(p)
  self.status = SENT_CHALLENGE
 def onAuthChallenge(self, packet):
  if packet.result == AUTH_SUCCESS:
   self.A, self.a = SRP.client_begin(self.username)
   self.K, self.m = SRP.client_key(self.username, self.password, packet.s, packet.B, self.A, self.a)
   proof = packets.CAuthProof()
   proof.A, proof.cM = self.A, self.m
   self.send(proof)
   self.status = SENT_PROOF
  else:
   self.transport.loseConnection()
   self.factory.authFailed(packet.result)
 def onAuthProof(self, packet):
  if packet.result == AUTH_SUCCESS:
   etalon = SRP.host_proof(self.K, self.A, self.m)
   proof = packet.proof
   if proof == etalon:
    self.status = AUTHENTICATED
    self.factory.authDone(self)
   else:
    self.transport.loseConnection()
    self.factory.authFailed(HOST_PROOF_FAILED)
  else:
   self.transport.loseConnection()
   self.factory.authFailed(packet.result)
 def onRealmList(self, packet):
  self.transport.loseConnection()
  self.factory.onRealmList(packet.realms, self.K)
 def requestRealmList(self):
  req = packets.CRealmList()
  self.send(req)

class RealmClientFactory(ClientFactory):
 
 protocol = RealmClientProtocol
 version = (2, 4, 3)
 build = 8606
 country = 'enGB'
 platform = 'x86'
 os = 'Win'
 username = ''
 password = ''

 def setAuthData(self, u, p):
  """This function called by user before connecting
  to set username and password
  it must UPPER() username and password"""
  self.username, self.password = u.upper(), p.upper()
 def authFailed(self, reason):
  """this function is called by protocol when authentication fails"""
  if reason == BANNED: print "We are banned on this server."
  elif reason == WRONG_BUILD_NUMBER: print "We are using wrong client build."
  elif reason == AUTH_NO_MATCH: print "Client authentication failed."
  elif reason == HOST_PROOF_FAILED: print "Host authentication failed."
  else: print "Connection failed for unknown reason. (errcode=%s)" % hex(reason)
 def authDone(self, proto):
  proto.requestRealmList()
 def onRealmList(self, realms, K):
  """This function is called when we have received realm list,
  here we should select one realm, and connect to,
  use K to encrypt connection with realm"""
  pass

